package com.clp.protocol.iec104.iec104.client.state;

import com.clp.protocol.core.exception.FailedToSendFrameException;
import com.clp.protocol.iec104.iec104.apdu.Apdu;
import com.clp.protocol.iec104.iec104.apdu.asdu.Cot;
import com.clp.protocol.iec104.iec104.apdu.asdu.IAsdu;
import com.clp.protocol.iec104.iec104.apdu.asdu.infoobj.InfoObj;
import com.clp.protocol.iec104.iec104.apdu.asdu.infoobj.infoelem.TaInfoElem;
import com.clp.protocol.iec104.iec104.apdu.asdu.infoobj.qua.C_SE_NA_1_Qua;
import com.clp.protocol.iec104.iec104.apdu.asdu.infoobj.qua.C_SE_NB_1_Qua;
import com.clp.protocol.iec104.iec104.apdu.asdu.infoobj.qua.C_SE_NC_1_Qua;
import com.clp.protocol.iec104.iec104.client.async.MasterPromise;
import com.clp.protocol.iec104.iec104.client.async.sendapdu.SendTaExecuteMasterPromise;
import com.clp.protocol.iec104.iec104.client.async.sendapdu.SendTaSelectMasterPromise;
import com.clp.protocol.iec104.iec104.definition.Tm;
import com.clp.protocol.iec104.iec104.definition.TypeTag;
import com.clp.protocol.iec104.iec104.definition.quatype.TaQuaType;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

/**
 * 主站的遥调状态
 */
@Slf4j
public class TaMasterState extends AbstractMasterState {

    @Getter
    @AllArgsConstructor
    public enum State {
        /**
         * 遥调选择
         */
        SELECT("选择中"),
        /**
         * 遥调选择肯定确认
         */
        SELECT_ACK_YES("选择肯定确认"),
        /**
         * 遥调选择否定确认
         */
        SELECT_ACK_NO("选择否定确认"),
        /**
         * 遥调执行
         */
        EXECUTE("执行中"),
        /**
         * 遥调执行肯定确认
         */
        EXECUTE_ACK_YES("执行肯定确认"),
        /**
         * 遥调执行否定确认
         */
        EXECUTE_ACK_NO("执行否定确认"),
        /**
         * 遥调执行结束
         */
        END("空闲");

        private final String desc;
    }

    public interface PtState {
        int getRtuAddr();
        int getAddr();
        Tm.ValType valType();
        Number getVal();
        State getState();
    }

    /**
     * 遥调点状态
     */
    @Data
    @Accessors(chain = true)
    private static class PtStateImpl implements PtState {
        private final int rtuAddr;
        private final int addr;
        private volatile State state;
        private final int ptType; // 1为归一化值，2为标度化值，3为短浮点数
        private final Number val;

        private volatile Date lastSelectTime;
        private volatile Date lastSelectAckYesTime;
        private volatile Date lastSelectAckNoTime;
        private volatile Date lastExecuteTime;
        private volatile Date lastExecuteAckYesTime;
        private volatile Date lastExecuteAckNoTime;
        private volatile Date lastExecuteFinishedTime;

        private PtStateImpl(int rtuAddr, int addr, int ptType, Number val) {
            this.rtuAddr = rtuAddr;
            this.addr = addr;
            this.ptType = ptType;
            this.val = val;
            this.reset();
        }

        public static PtStateImpl newNormalizedInstance(int rtuAddr, int addr, Number val) {
            return new PtStateImpl(rtuAddr, addr, 1, val);
        }

        public static PtStateImpl newScaledInstance(int rtuAddr, int addr, Number val) {
            return new PtStateImpl(rtuAddr, addr, 2, val);
        }

        public static PtStateImpl newFloatInstance(int rtuAddr, int addr, Number val) {
            return new PtStateImpl(rtuAddr, addr, 3, val);
        }

        private void reset() {
            this.state = State.END;
            this.lastSelectTime = new Date();
            this.lastSelectAckYesTime = new Date();
            this.lastSelectAckNoTime = new Date();
            this.lastExecuteTime = new Date();
            this.lastExecuteAckYesTime = new Date();
            this.lastExecuteAckNoTime = new Date();
            this.lastExecuteFinishedTime = new Date();
        }

        @Override
        public Tm.ValType valType() {
            switch (ptType) {
                case 1:
                    return Tm.ValType.NORMALIZE;
                case 2:
                    return Tm.ValType.SCALED;
                case 3:
                    return Tm.ValType.FLOAT;
            }
            throw new RuntimeException("不应到达");
        }

        @Override
        public Number getVal() {
            return val;
        }

        public boolean isEndState() {
            return state == State.END;
        }

        public boolean isNormalized() {
            return ptType == 1;
        }

        public boolean isScaled() {
            return ptType == 2;
        }

        public boolean isFloat() {
            return ptType == 3;
        }

        public boolean isDoingSelect() {
            return state == State.SELECT;
        }

        public boolean isDoingExecute() {
            return state == State.EXECUTE;
        }
    }

    private static class PtStateMap {
        private Map<String, PtStateImpl> psMap;

        private PtStateMap() {
            this.psMap = new HashMap<>();
        }

        private String genKey(int rtuAddr, int addr) {
            return "" + rtuAddr + "-" + addr;
        }

        public synchronized PtStateImpl put(int rtuAddr, int addr, PtStateImpl ptStateImpl) {
            return psMap.put(genKey(rtuAddr, addr), ptStateImpl);
        }

        public synchronized PtStateImpl get(int rtuAddr, int addr) {
            return psMap.get(genKey(rtuAddr, addr));
        }

        public synchronized boolean containsKey(int rtuAddr, int addr) {
            return psMap.containsKey(genKey(rtuAddr, addr));
        }

        public synchronized void forEach(BiConsumer<String, PtState> consumer) {
            psMap.forEach(consumer);
        }

        public synchronized PtStateImpl remove(int rtuAddr, int addr) {
            return psMap.remove(genKey(rtuAddr, addr));
        }

        public synchronized int size() {
            return psMap.size();
        }

        public synchronized void reset() {
            psMap.clear();
        }
    }

    private final PtStateMap ptStateMap;
    private final PromiseMap<SendTaSelectMasterPromise> selectPromiseMap;
    private final PromiseMap<SendTaExecuteMasterPromise> executePromiseMap;

    public TaMasterState(InMasterStateManager stateManager) {
        super(stateManager);
        this.ptStateMap = new PtStateMap();
        this.selectPromiseMap = new PromiseMap<>();
        this.executePromiseMap = new PromiseMap<>();
        resetState();
    }

    @Override
    protected Future<Void> resetState() {
        Promise<Void> promise = createPromise(Void.class);
        ptStateMap.reset();
        return promise.setSuccess(null);
    }

    @Override
    protected Future<Void> refreshState() {
        return resetState();
    }

    @Override
    public Apdu updateStateBySending(Apdu apdu) {
        if (apdu == null || !apdu.isIType()) return apdu;

        IAsdu iAsdu = apdu.castToIType().getIAsdu();
        TypeTag typeTag = iAsdu.getTypeTag();
        Cot cot = iAsdu.getCot();
        int rtuAddr = iAsdu.getRtuAddr();

        InfoObj infoObj;
        int addr;
        TaQuaType taQuaType;
        PtStateImpl ptStateImpl;
        switch (typeTag) {
            case C_SE_NA_1: // 归一化值
                infoObj = iAsdu.getInfoObjs().get(0);
                // 公共地址
                addr = infoObj.getAddr();
                TaInfoElem taInfoElem = infoObj.getInfoElem().castToTaInfoElem();
                taQuaType = infoObj.getQua().castTo(C_SE_NA_1_Qua.class).getType();
                ptStateImpl = ptStateMap.get(rtuAddr, addr);

                switch (cot.getCause()) {
                    case COT_ACT: // 激活
                        switch (taQuaType) {
                            case SELECT:
                                // 校验
                                if (ptStateImpl != null) {
                                    log.warn("已存在相同信息体地址的遥调过程，放弃本次选择命令({})", addr);
                                    selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendSelectSuccess(false).setRecvSelectAckYes(false).setRecvSelectAckNo(false).setFailDesc("已存在相同信息体地址的遥调命令过程");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                // 校验通过，添加新测点的遥控状态
                                ptStateMap.put(rtuAddr, addr, PtStateImpl.newNormalizedInstance(rtuAddr, addr, taInfoElem.getNumberVal()).setState(State.SELECT).setLastSelectTime(new Date()));
                                log.info("发送新的遥调选择报文({})", addr);
                                break;
                            case EXECUTE:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isNormalized()) {
                                    log.warn("发送的遥调执行报文不存在对应的过程，该报文已放弃发送！({})", addr);
                                    executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendExecuteSuccess(false).setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("已存在相同信息体地址的遥调命令过程");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                if (ptStateImpl.state != State.SELECT_ACK_YES) {
                                    log.error("未收到遥调选择肯定确认报文，放弃本次遥调执行命令({})", addr);
                                    executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendExecuteSuccess(false).setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("未收到遥调选择肯定确认报文，放弃本次遥调命令");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                // 校验通过
                                ptStateImpl.setState(State.EXECUTE).setLastExecuteTime(new Date());
                                log.info("发送遥调执行报文({})", addr);
                                break;
                        }
                        break;
                }
                break;
            case C_SE_NB_1: // 标度化值
                infoObj = iAsdu.getInfoObjs().get(0);
                // 公共地址
                addr = infoObj.getAddr();
                taInfoElem = infoObj.getInfoElem().castToTaInfoElem();
                taQuaType = infoObj.getQua().castTo(C_SE_NB_1_Qua.class).getType();
                ptStateImpl = ptStateMap.get(rtuAddr, addr);

                switch (cot.getCause()) {
                    case COT_ACT: // 激活
                        switch (taQuaType) {
                            case SELECT:
                                // 校验
                                if (ptStateImpl != null) {
                                    log.warn("已存在相同信息体地址的遥调过程，放弃本次选择命令({})", addr);
                                    selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendSelectSuccess(false).setRecvSelectAckYes(false).setRecvSelectAckNo(false).setFailDesc("已存在相同信息体地址的遥调命令过程");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                // 校验通过，添加新测点的遥控状态
                                ptStateMap.put(rtuAddr, addr, PtStateImpl.newScaledInstance(rtuAddr, addr, taInfoElem.getNumberVal()).setState(State.SELECT).setLastSelectTime(new Date()));
                                log.info("发送新的遥调选择报文({})", addr);
                                break;
                            case EXECUTE:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isScaled()) {
                                    log.warn("发送的遥调执行报文不存在对应的过程，该报文已放弃发送！({})", addr);
                                    executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendExecuteSuccess(false).setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("已存在相同信息体地址的遥调命令过程");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                if (ptStateImpl.state != State.SELECT_ACK_YES) {
                                    log.error("未收到遥调选择肯定确认报文，放弃本次遥调执行命令({})", addr);
                                    executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendExecuteSuccess(false).setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("未收到遥调选择肯定确认报文，放弃本次遥调命令");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                // 校验通过
                                ptStateImpl.setState(State.EXECUTE).setLastExecuteTime(new Date());
                                log.info("发送遥调执行报文({})", addr);
                                break;
                        }
                        break;
                }
                break;
            case C_SE_NC_1: // 短浮点数
                infoObj = iAsdu.getInfoObjs().get(0);
                // 公共地址
                addr = infoObj.getAddr();
                taInfoElem = infoObj.getInfoElem().castToTaInfoElem();
                taQuaType = infoObj.getQua().castTo(C_SE_NC_1_Qua.class).getType();
                ptStateImpl = ptStateMap.get(rtuAddr, addr);

                switch (cot.getCause()) {
                    case COT_ACT: // 激活
                        switch (taQuaType) {
                            case SELECT:
                                // 校验
                                if (ptStateImpl != null) {
                                    log.warn("已存在相同信息体地址的遥调过程，放弃本次选择命令({})", addr);
                                    selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendSelectSuccess(false).setRecvSelectAckYes(false).setRecvSelectAckNo(false).setFailDesc("已存在相同信息体地址的遥调命令过程");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                // 校验通过，添加新测点的遥控状态
                                ptStateMap.put(rtuAddr, addr, PtStateImpl.newFloatInstance(rtuAddr, addr, taInfoElem.getNumberVal()).setState(State.SELECT).setLastSelectTime(new Date()));
                                log.info("发送新的遥调选择报文({})", addr);
                                break;
                            case EXECUTE:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isFloat()) {
                                    log.warn("发送的遥调执行报文不存在对应的过程，该报文已放弃发送！({})", addr);
                                    executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendExecuteSuccess(false).setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("已存在相同信息体地址的遥调命令过程");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                if (ptStateImpl.state != State.SELECT_ACK_YES) {
                                    log.error("未收到遥调选择肯定确认报文，放弃本次遥调执行命令({})", addr);
                                    executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                        promise.getRes().setSendExecuteSuccess(false).setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("未收到遥调选择肯定确认报文，放弃本次遥调命令");
                                        promise.setFailure(new FailedToSendFrameException(apdu));
                                        return true;
                                    });
                                    return null;
                                }
                                // 校验通过
                                ptStateImpl.setState(State.EXECUTE).setLastExecuteTime(new Date());
                                log.info("发送遥调执行报文({})", addr);
                                break;
                        }
                        break;
                }
                break;
        }
        return apdu;
    }

    @Override
    public Apdu updateStateByRecving(Apdu apdu) {
        if (apdu == null || !apdu.isIType()) return apdu;

        IAsdu iAsdu = apdu.castToIType().getIAsdu();
        TypeTag typeTag = iAsdu.getTypeTag();
        Cot cot = iAsdu.getCot();
        int rtuAddr = iAsdu.getRtuAddr();

        InfoObj infoObj;
        int addr;
        TaQuaType taQuaType;
        PtStateImpl ptStateImpl;
        switch (typeTag) {
            case C_SE_NA_1: // 归一化值
                infoObj = iAsdu.getInfoObjs().get(0);
                // 公共地址
                addr = infoObj.getAddr();
                taQuaType = infoObj.getQua().castTo(C_SE_NA_1_Qua.class).getType();
                ptStateImpl = ptStateMap.get(rtuAddr, addr);

                switch (cot.getCause()) {
                    case COT_ACTCON: // 确认激活
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isNormalized()) {
                                    log.error("收到的遥调选择确认报文不存在对应的过程！({})", addr);
                                    break;
                                }
                                if (ptStateImpl.state != State.SELECT) {
                                    log.warn("接收到无效的遥调选择确认报文({})", addr);
                                    break;
                                }
                                // 校验通过
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        ptStateImpl.setState(State.SELECT_ACK_YES).setLastSelectAckYesTime(new Date());
                                        log.info("收到遥调选择肯定确认报文({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false);
                                            promise.setSuccess();
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        ptStateImpl.setState(State.SELECT_ACK_NO).setLastSelectAckNoTime(new Date());
                                        log.info("收到遥调选择否定确认报文({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文"));
                                            return true;
                                        });

                                        // 从列表中移除
                                        ptStateImpl.setState(State.END);
                                        ptStateMap.remove(rtuAddr, addr);
                                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                                        break;
                                }
                                break;
                            case EXECUTE:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isNormalized()) {
                                    log.error("收到的遥调执行确认报文不存在对应的过程！({})", addr);
                                    break;
                                }
                                if (ptStateImpl.state != State.EXECUTE) {
                                    log.warn("接收到无效的遥调执行确认报文({})", addr);
                                    break;
                                }
                                // 校验通过
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        ptStateImpl.setState(State.EXECUTE_ACK_YES).setLastExecuteAckYesTime(new Date());
                                        log.info("收到遥调执行肯定确认报文({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false);
                                            return false;
                                        });
                                        break;
                                    case PN_NO:
                                        ptStateImpl.setState(State.EXECUTE_ACK_NO).setLastExecuteAckNoTime(new Date());
                                        log.info("收到遥调执行否定确认报文({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文"));
                                            return true;
                                        });

                                        // 从列表中移除
                                        ptStateImpl.setState(State.END);
                                        ptStateMap.remove(rtuAddr, addr);
                                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                                        break;
                                }
                                break;
                        }
                        break;
                    case COT_ACTTERM:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isNormalized()) {
                            log.error("收到的遥调激活终止报文不存在对应的过程！({})", addr);
                            break;
                        }
                        if (ptStateImpl.state != State.EXECUTE_ACK_YES) {
                            log.warn("接收到无效的遥调激活重置报文({})", addr);
                            break;
                        }
                        // 校验通过
                        ptStateImpl.setState(State.END).setLastExecuteFinishedTime(new Date());
                        log.info("收到遥调激活终止报文({})", addr);
                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                            promise.getRes().setRecvEnd(true);
                            promise.setSuccess();
                            return true;
                        });

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                        break;
                    case COT_UNKNOW_TYPE:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isNormalized()) {
                            log.warn("收到的遥调报文不存在对应的过程！({})", addr);
                            break;
                        }
                        // 校验通过
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                if (ptStateImpl.state != State.SELECT) {
                                    log.warn("接收到无效的遥调报文（未知的类型标识）({})", addr);
                                    break;
                                }
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调选择肯定确认报文（未知的类型标识）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false).setFailDesc("收到遥调选择肯定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调选择肯定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调选择否定确认报文（未知的类型标识）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                            case EXECUTE:
                                if (ptStateImpl.state != State.EXECUTE) {
                                    log.warn("接收到无效的遥调报文（未知的类型标识）({})", addr);
                                    break;
                                }
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调执行肯定确认报文（未知的类型标识）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行肯定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调执行肯定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调执行否定确认报文（未知的类型标识）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(true).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                        }
                        ptStateImpl.setState(State.END);

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({})，剩余过程数：({})", addr, ptStateMap.size());
                        break;
                    case COT_UNKNOW_INF:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isNormalized()) {
                            log.warn("收到的遥调报文不存在对应的过程！({})", addr);
                            break;
                        }
                        if (ptStateImpl.state != State.SELECT || ptStateImpl.state != State.EXECUTE) {
                            log.warn("接收到无效的遥调报文（未知的信息体对象地址）({})", addr);
                            break;
                        }
                        // 校验通过
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调选择肯定确认报文（未知的信息体对象地址）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false).setFailDesc("收到遥调选择肯定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调选择肯定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调选择否定确认报文（未知的信息体对象地址）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                            case EXECUTE:
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调执行肯定确认报文（未知的信息体对象地址）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行肯定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调执行肯定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调执行否定确认报文（未知的信息体对象地址）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(true).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                        }
                        ptStateImpl.setState(State.END);

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({})，剩余过程数：({})", addr, ptStateMap.size());
                        break;
                }
                break;
            case C_SE_NB_1: // 标度化值
                infoObj = iAsdu.getInfoObjs().get(0);
                // 公共地址
                addr = infoObj.getAddr();
                taQuaType = infoObj.getQua().castTo(C_SE_NB_1_Qua.class).getType();
                ptStateImpl = ptStateMap.get(rtuAddr, addr);

                switch (cot.getCause()) {
                    case COT_ACTCON: // 确认激活
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isScaled()) {
                                    log.error("收到的遥调选择确认报文不存在对应的过程！({})", addr);
                                    break;
                                }
                                if (ptStateImpl.state != State.SELECT) {
                                    log.warn("接收到无效的遥调选择确认报文({})", addr);
                                    break;
                                }
                                // 校验通过
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        ptStateImpl.setState(State.SELECT_ACK_YES).setLastSelectAckYesTime(new Date());
                                        log.info("收到遥调选择肯定确认报文({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false);
                                            promise.setSuccess();
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        ptStateImpl.setState(State.SELECT_ACK_NO).setLastSelectAckNoTime(new Date());
                                        log.info("收到遥调选择否定确认报文({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文"));
                                            return true;
                                        });

                                        // 从列表中移除
                                        ptStateImpl.setState(State.END);
                                        ptStateMap.remove(rtuAddr, addr);
                                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                                        break;
                                }
                                break;
                            case EXECUTE:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isNormalized()) {
                                    log.error("收到的遥调执行确认报文不存在对应的过程！({})", addr);
                                    break;
                                }
                                if (ptStateImpl.state != State.EXECUTE) {
                                    log.warn("接收到无效的遥调执行确认报文({})", addr);
                                    break;
                                }
                                // 校验通过
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        ptStateImpl.setState(State.EXECUTE_ACK_YES).setLastExecuteAckYesTime(new Date());
                                        log.info("收到遥调执行肯定确认报文({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false);
                                            return false;
                                        });
                                        break;
                                    case PN_NO:
                                        ptStateImpl.setState(State.EXECUTE_ACK_NO).setLastExecuteAckNoTime(new Date());
                                        log.info("收到遥调执行否定确认报文({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文"));
                                            return true;
                                        });

                                        // 从列表中移除
                                        ptStateImpl.setState(State.END);
                                        ptStateMap.remove(rtuAddr, addr);
                                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                                        break;
                                }
                                break;
                        }
                        break;
                    case COT_ACTTERM:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isScaled()) {
                            log.error("收到的遥调激活终止报文不存在对应的过程！({})", addr);
                            break;
                        }
                        if (ptStateImpl.state != State.EXECUTE_ACK_YES) {
                            log.warn("接收到无效的遥调激活重置报文({})", addr);
                            break;
                        }
                        // 校验通过
                        ptStateImpl.setState(State.END).setLastExecuteFinishedTime(new Date());
                        log.info("收到遥调激活终止报文({})", addr);
                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                            promise.getRes().setRecvEnd(true);
                            promise.setSuccess();
                            return true;
                        });

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                        break;
                    case COT_UNKNOW_TYPE:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isScaled()) {
                            log.warn("收到的遥调报文不存在对应的过程！({})", addr);
                            break;
                        }
                        // 校验通过
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                if (ptStateImpl.state != State.SELECT) {
                                    log.warn("接收到无效的遥调报文（未知的类型标识）({})", addr);
                                    break;
                                }
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调选择肯定确认报文（未知的类型标识）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false).setFailDesc("收到遥调选择肯定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调选择肯定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调选择否定确认报文（未知的类型标识）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                            case EXECUTE:
                                if (ptStateImpl.state != State.EXECUTE) {
                                    log.warn("接收到无效的遥调报文（未知的类型标识）({})", addr);
                                    break;
                                }
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调执行肯定确认报文（未知的类型标识）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行肯定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调执行肯定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调执行否定确认报文（未知的类型标识）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(true).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                        }
                        ptStateImpl.setState(State.END);

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({})，剩余过程数：({})", addr, ptStateMap.size());
                        break;
                    case COT_UNKNOW_INF:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isScaled()) {
                            log.warn("收到的遥调报文不存在对应的过程！({})", addr);
                            break;
                        }
                        if (ptStateImpl.state != State.SELECT || ptStateImpl.state != State.EXECUTE) {
                            log.warn("接收到无效的遥调报文（未知的信息体对象地址）({})", addr);
                            break;
                        }
                        // 校验通过
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调选择肯定确认报文（未知的信息体对象地址）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false).setFailDesc("收到遥调选择肯定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调选择肯定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调选择否定确认报文（未知的信息体对象地址）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                            case EXECUTE:
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调执行肯定确认报文（未知的信息体对象地址）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行肯定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调执行肯定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调执行否定确认报文（未知的信息体对象地址）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(true).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                        }
                        ptStateImpl.setState(State.END);

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({})，剩余过程数：({})", addr, ptStateMap.size());
                        break;
                }
                break;
            case C_SE_NC_1:
                infoObj = iAsdu.getInfoObjs().get(0);
                // 公共地址
                addr = infoObj.getAddr();
                taQuaType = infoObj.getQua().castTo(C_SE_NC_1_Qua.class).getType();
                ptStateImpl = ptStateMap.get(rtuAddr, addr);

                switch (cot.getCause()) {
                    case COT_ACTCON: // 确认激活
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isFloat()) {
                                    log.error("收到的遥调选择确认报文不存在对应的过程！({})", addr);
                                    break;
                                }
                                if (ptStateImpl.state != State.SELECT) {
                                    log.warn("接收到无效的遥调选择确认报文({})", addr);
                                    break;
                                }
                                // 校验通过
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        ptStateImpl.setState(State.SELECT_ACK_YES).setLastSelectAckYesTime(new Date());
                                        log.info("收到遥调选择肯定确认报文({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false);
                                            promise.setSuccess();
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        ptStateImpl.setState(State.SELECT_ACK_NO).setLastSelectAckNoTime(new Date());
                                        log.info("收到遥调选择否定确认报文({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文"));
                                            return true;
                                        });

                                        // 从列表中移除
                                        ptStateImpl.setState(State.END);
                                        ptStateMap.remove(rtuAddr, addr);
                                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                                        break;
                                }
                                break;
                            case EXECUTE:
                                // 校验
                                if (ptStateImpl == null || !ptStateImpl.isNormalized()) {
                                    log.error("收到的遥调执行确认报文不存在对应的过程！({})", addr);
                                    break;
                                }
                                if (ptStateImpl.state != State.EXECUTE) {
                                    log.warn("接收到无效的遥调执行确认报文({})", addr);
                                    break;
                                }
                                // 校验通过
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        ptStateImpl.setState(State.EXECUTE_ACK_YES).setLastExecuteAckYesTime(new Date());
                                        log.info("收到遥调执行肯定确认报文({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false);
                                            return false;
                                        });
                                        break;
                                    case PN_NO:
                                        ptStateImpl.setState(State.EXECUTE_ACK_NO).setLastExecuteAckNoTime(new Date());
                                        log.info("收到遥调执行否定确认报文({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文"));
                                            return true;
                                        });

                                        // 从列表中移除
                                        ptStateImpl.setState(State.END);
                                        ptStateMap.remove(rtuAddr, addr);
                                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                                        break;
                                }
                                break;
                        }
                        break;
                    case COT_ACTTERM:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isFloat()) {
                            log.error("收到的遥调激活终止报文不存在对应的过程！({})", addr);
                            break;
                        }
                        if (ptStateImpl.state != State.EXECUTE_ACK_YES) {
                            log.warn("接收到无效的遥调激活重置报文({})", addr);
                            break;
                        }
                        // 校验通过
                        ptStateImpl.setState(State.END).setLastExecuteFinishedTime(new Date());
                        log.info("收到遥调激活终止报文({})", addr);
                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                            promise.getRes().setRecvEnd(true);
                            promise.setSuccess();
                            return true;
                        });

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({}), 剩余过程数：({})", addr, ptStateMap.size());
                        break;
                    case COT_UNKNOW_TYPE:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isFloat()) {
                            log.warn("收到的遥调报文不存在对应的过程！({})", addr);
                            break;
                        }
                        // 校验通过
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                if (ptStateImpl.state != State.SELECT) {
                                    log.warn("接收到无效的遥调报文（未知的类型标识）({})", addr);
                                    break;
                                }
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调选择肯定确认报文（未知的类型标识）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false).setFailDesc("收到遥调选择肯定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调选择肯定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调选择否定确认报文（未知的类型标识）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                            case EXECUTE:
                                if (ptStateImpl.state != State.EXECUTE) {
                                    log.warn("接收到无效的遥调报文（未知的类型标识）({})", addr);
                                    break;
                                }
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调执行肯定确认报文（未知的类型标识）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行肯定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调执行肯定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调执行否定确认报文（未知的类型标识）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(true).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文（未知的类型标识）");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文（未知的类型标识）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                        }
                        ptStateImpl.setState(State.END);

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({})，剩余过程数：({})", addr, ptStateMap.size());
                        break;
                    case COT_UNKNOW_INF:
                        // 校验
                        if (ptStateImpl == null || ptStateImpl.isFloat()) {
                            log.warn("收到的遥调报文不存在对应的过程！({})", addr);
                            break;
                        }
                        if (ptStateImpl.state != State.SELECT || ptStateImpl.state != State.EXECUTE) {
                            log.warn("接收到无效的遥调报文（未知的信息体对象地址）({})", addr);
                            break;
                        }
                        // 校验通过
                        switch (taQuaType) { // 命令类型
                            case SELECT:
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调选择肯定确认报文（未知的信息体对象地址）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(true).setRecvSelectAckNo(false).setFailDesc("收到遥调选择肯定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调选择肯定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调选择否定确认报文（未知的信息体对象地址）({})", addr);
                                        selectPromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(true).setFailDesc("收到遥调选择否定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调选择否定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                            case EXECUTE:
                                switch (cot.getPn()) { // 肯定或否定确认
                                    case PN_YES:
                                        log.warn("收到遥调执行肯定确认报文（未知的信息体对象地址）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(true).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("收到遥调执行肯定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调执行肯定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                    case PN_NO:
                                        log.warn("收到遥调执行否定确认报文（未知的信息体对象地址）({})", addr);
                                        executePromiseMap.removeIf(rtuAddr, addr, promise -> {
                                            promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(true).setRecvEnd(false).setFailDesc("收到遥调执行否定确认报文（未知的信息体对象地址）");
                                            promise.setFailure(new RuntimeException("收到遥调执行否定确认报文（未知的信息体对象地址）"));
                                            return true;
                                        });
                                        break;
                                }
                                break;
                        }
                        ptStateImpl.setState(State.END);

                        // 从列表中移除
                        ptStateMap.remove(rtuAddr, addr);
                        log.info("已移除遥调过程({})，剩余过程数：({})", addr, ptStateMap.size());
                        break;
                }
                break;
        }

        return apdu;
    }

    @Override
    protected ScheduledTask getScheduledTask() {
        return new ScheduledTask(0, 1, TimeUnit.SECONDS) {
            @Override
            public void run() {
                if (!getStateManager().getInMaster().stateInfo().isRecvedInitEnd()) {
                    return;
                }

                for (Iterator<Map.Entry<String, PtStateImpl>> iterator = ptStateMap.psMap.entrySet().iterator(); iterator.hasNext();) {
                    Map.Entry<String, PtStateImpl> entry = iterator.next();
                    PtStateImpl ptStateImpl = entry.getValue();
                    switch (ptStateImpl.state) {
                        case SELECT:
                            // 遥调确认选择超时情况的处理
                            if (new Date().getTime() - ptStateImpl.lastSelectTime.getTime() > 10 * 1000) {
                                log.error("发送遥调选择10秒后未收到确认，放弃本次遥调请求");
                                selectPromiseMap.removeIf(ptStateImpl.rtuAddr, ptStateImpl.addr, promise -> {
                                    promise.getRes().setRecvSelectAckYes(false).setRecvSelectAckNo(false).setFailDesc("遥调选择确认超时");
                                    promise.setFailure(new RuntimeException("遥调选择确认超时"));
                                    return true;
                                });
                                ptStateImpl.state = State.END;
                                iterator.remove();
                                log.error("因超时移除遥调过程({}), 移除后剩余遥调过程数：({})", ptStateImpl.addr, ptStateMap.size());
                            }
                            break;
                        case SELECT_ACK_YES:
                            // 处理发送遥调执行超时
                            if (new Date().getTime() - ptStateImpl.lastSelectAckYesTime.getTime() > 3 * 1000) {
                                log.error("收到遥调选择肯定确认报文3秒后未发送遥调执行，放弃本次遥调请求({})", ptStateImpl.addr);
                                ptStateImpl.state = State.END;
                                iterator.remove();
                                log.error("因超时移除遥调过程({}), 移除后剩余过程数：({})", ptStateImpl.addr, ptStateMap.size());
                            }
                            break;
                        case SELECT_ACK_NO:
                            // 进入该状态说明接收到了遥调选择否定确认/未知的信息体地址，要重置状态（已经重置）
                            break;
                        case EXECUTE:
                            // 遥调执行确认超时情况的处理
                            if (new Date().getTime() - ptStateImpl.lastExecuteTime.getTime() > 10 * 1000) {
                                log.error("发送遥调执行10秒后未收到确认，放弃本次遥调请求({})", ptStateImpl.addr);
                                executePromiseMap.removeIf(ptStateImpl.rtuAddr, ptStateImpl.addr, promise -> {
                                    promise.getRes().setRecvExecuteAckYes(false).setRecvExecuteAckNo(false).setRecvEnd(false).setFailDesc("发送遥调执行10秒后未收到确认，放弃本次遥调请求");
                                    promise.setFailure(new RuntimeException("遥调执行确认超时"));
                                    return true;
                                });
                                ptStateImpl.state = State.END;
                                iterator.remove();
                                log.error("因超时移除遥调过程({}), 移除后剩余过程数({})", ptStateImpl.addr, ptStateMap.size());
                            }
                            break;
                        case EXECUTE_ACK_YES:
                            // 进入该状态说明接收到了遥调执行确认报文，需要进行遥调执行结束超时情况的处理
                            if (new Date().getTime() - ptStateImpl.lastExecuteAckYesTime.getTime() > 10 * 1000) {
                                log.error("收到遥调执行确认10秒后未收到终止确认，放弃本次遥调请求");
                                executePromiseMap.removeIf(ptStateImpl.rtuAddr, ptStateImpl.addr, promise -> {
                                    promise.getRes().setRecvEnd(false).setFailDesc("收到遥调执行确认10秒后未收到终止确认，放弃本次遥调请求");
                                    promise.setFailure(new RuntimeException("遥调终止确认超时"));
                                    return true;
                                });
                                ptStateImpl.state = State.END;
                                iterator.remove();
                                log.error("因超时移除遥调过程({}), 移除后剩余过程数：({})", ptStateImpl.addr, ptStateMap.size());
                            }
                            break;
                        case EXECUTE_ACK_NO:
                            // 进入该状态说明接收到了遥调执行否定确认/未知的信息体对象地址 报文，要重置状态
                            break;
                        case END:
                            // 进入该状态说明接收到了遥调执行终止报文，本次请求顺利结束
                            break;
                    }
                }
            }
        };
    }

    @Override
    public <V> MasterPromise<V> register(MasterPromise<V> sendPromise) {
        if (sendPromise == null || sendPromise.getRes() == null) return sendPromise;

        if (sendPromise instanceof SendTaSelectMasterPromise) {
            SendTaSelectMasterPromise promise = (SendTaSelectMasterPromise) sendPromise;
            selectPromiseMap.put(promise.getRtuAddr(), promise.getAddr(), promise);
            return null;
        }
        if (sendPromise instanceof SendTaExecuteMasterPromise) {
            SendTaExecuteMasterPromise promise = (SendTaExecuteMasterPromise) sendPromise;
            executePromiseMap.put(promise.getRtuAddr(), promise.getAddr(), promise);
            return null;
        }

        return sendPromise;
    }

    public boolean isDoingTaSelectNormalized(int infoObjAddr) {
        synchronized (ptStateMap) {
            PtStateImpl ptStateImpl = ptStateMap.get(getStateManager().getInMaster().rtuAddr(), infoObjAddr);
            return ptStateImpl != null && ptStateImpl.isDoingSelect() && ptStateImpl.isNormalized();
        }
    }

    public boolean isDoingTaSelectScaled(int infoObjAddr) {
        synchronized (ptStateMap) {
            PtStateImpl ptStateImpl = ptStateMap.get(getStateManager().getInMaster().rtuAddr(), infoObjAddr);
            return ptStateImpl != null && ptStateImpl.isDoingSelect() && ptStateImpl.isScaled();
        }
    }

    public boolean isDoingTaSelectFloat(int infoObjAddr) {
        synchronized (ptStateMap) {
            PtStateImpl ptStateImpl = ptStateMap.get(getStateManager().getInMaster().rtuAddr(), infoObjAddr);
            return ptStateImpl != null && ptStateImpl.isDoingSelect() && ptStateImpl.isFloat();
        }
    }

    public boolean isDoingTaExecuteNormalized(int infoObjAddr) {
        synchronized (ptStateMap) {
            PtStateImpl ptStateImpl = ptStateMap.get(getStateManager().getInMaster().rtuAddr(), infoObjAddr);
            return ptStateImpl != null && ptStateImpl.isDoingExecute() && ptStateImpl.isNormalized();
        }
    }

    public boolean isDoingTaExecuteScaled(int infoObjAddr) {
        synchronized (ptStateMap) {
            PtStateImpl ptStateImpl = ptStateMap.get(getStateManager().getInMaster().rtuAddr(), infoObjAddr);
            return ptStateImpl != null && ptStateImpl.isDoingExecute() && ptStateImpl.isScaled();
        }
    }

    public boolean isDoingTaExecuteFloat(int infoObjAddr) {
        synchronized (ptStateMap) {
            PtStateImpl ptStateImpl = ptStateMap.get(getStateManager().getInMaster().rtuAddr(), infoObjAddr);
            return ptStateImpl != null && ptStateImpl.isDoingExecute() && ptStateImpl.isFloat();
        }
    }

    public List<PtState> listAllDoingTaPtStates() {
        return new ArrayList<>(ptStateMap.psMap.values());
    }
}
